package com.capgemini.simpleappblanche.dao.impl;

import java.util.List;

import javax.persistence.TypedQuery;

import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import com.capgemini.simpleappblanche.dao.ICustomerDao;
import com.capgemini.simpleappblanche.domain.customer.Customer;
import com.capgemini.simpleappblanche.dto.SearchCustomerCriteria;
import com.capgemini.simpleappblanche.utils.AbstractDaoJpaBase;

/**
 * @author jcdorchies
 *
 */
@Repository
public class CustomerDao extends AbstractDaoJpaBase<Customer, Long> implements ICustomerDao {
	
	private static final String DATA_WILDCARD = "%";
	
	/**
	 * {@inheritDoc}
	 * @see com.capgemini.simpleappblanche.dao.ICustomerDao#findByCriteria(com.capgemini.simpleappblanche.dto.SearchCustomerCriteria, int)
	 * TODO GWAI : ask for advice with dynamic request
	 * Warning this method is limit to 999 agencies
	 */
	@Override
	public List<Customer> findByCriteria(final SearchCustomerCriteria criteria,int nbElement) {
		logger.info("begin find by criteria dao");
		logger.info("criteria = "+criteria);
		
		//init request
		final StringBuilder queryStr = new StringBuilder();
		
		queryStr.append("from ")
			.append(this.getEntityName() )
			.append(" customer ");
		//if agency add join
		if(criteria.getAgencyId()!=null || (criteria.getAgenciesId()!=null && criteria.getAgenciesId().size()>0)){
		    queryStr.append(" left join fetch customer.agencies agency");
		}
		
		//always true condition to put where
		queryStr.append(" where customer.id is not null");
		
		//name criteria
		if(StringUtils.hasText(criteria.getName())){
		    queryStr.append(" and customer.name like :name ");
		}
		//agency criteria
		if(criteria.getAgencyId()!=null){
            queryStr.append(" and exists ( select c.id from " + this.getEntityName() + " c inner join c.agencies a where c.id =customer.id and a.id = :agencyId ) ");
        }
		if(criteria.getAgenciesId()!=null && criteria.getAgenciesId().size()>0){
            queryStr.append(" and exists ( select c.id from " + this.getEntityName() + " c inner join c.agencies a where c.id =customer.id and a.id in :agenciesId ) ");
        }
		
		//order
		queryStr.append(" order by customer.name, customer.firstname");
		
		
		final TypedQuery<Customer> query =  getEntityManager().createQuery(queryStr.toString(), Customer.class);
		//name parameter
		if(StringUtils.hasText(criteria.getName())){
		    query.setParameter("name", criteria.getName()+DATA_WILDCARD);
		}
		//agency parameter
		if(criteria.getAgencyId()!=null){
            query.setParameter("agencyId", criteria.getAgencyId());
        }
        if(criteria.getAgenciesId()!=null && criteria.getAgenciesId().size()>0){
            query.setParameter("agenciesId", criteria.getAgenciesId());
        }
        
		//set Max result
		query.setMaxResults(nbElement);
		
		//execute request
		final List<Customer> result = query.getResultList();
		
		logger.info("end find by criteria dao");
		return result;
	}

}
